home *** CD-ROM | disk | FTP | other *** search
- { traptime -- A program to time various methods of doing a toolbox trap:
- The usual method, calling a user-written routine to do the work, doing the
- work in-line, and calling the ROM routine directly without going through
- the trap dispatcher. Times for all routines are written on the screen in
- ticks for a given number of calls, then the number of calls is varied for
- improved accuracy.
-
- Mike Morton, November 1985. Modified for TML Pascal, June 1986. }
-
- program traptime (output); { "(output)" lets us do writelns }
-
- {$I MemTypes.ipas }
- {$I QuickDraw.ipas } { we use Quickdraw graphics }
- {$I OSIntf.ipas } { and OS definitions }
- {$I ToolIntf.ipas } { and Toolbox calls }
-
- var { program-wide variables }
- basetime: longint; { constant overhead for the loop }
- loops: longint; { number of iterations to time }
- start: longint; { starting tickcount for timing }
- Event:EventRecord;
- DoIt: Boolean;
- Finished:Boolean;
-
- { getbasetime -- Find the time for the loop when nothing is done inside it.
- This tells us the overhead which should be subtracted from other timings. }
- function getbasetime: longint;
- var count: longint; { loop counter }
- begin;
- start := tickcount; { snapshot starting time }
- for count := 1 to loops do { loop a bunch of times... }
- ; { ...doing nothing each time }
- getbasetime := tickcount-start; { calculate elapsed time }
- end; { function "getbasetime" }
-
- { usualtime -- Find the time used to call the ROM the usual way. This, and
- all timing routines, should look as much as possible like "getbasetime". }
- function usualtime: longint;
- var
- count: longint; { loop counter }
- pt: point; { point to assign to }
- x, y: integer; { coordinates to assign to the point }
- begin;
- start := tickcount; { snapshot starting time }
- for count := 1 to loops do { this time, inside the loop... }
- setpt (pt, x, y); { ...we do the ROM call }
- usualtime := tickcount-start; { calculate elapsed time }
- end; { function "usualtime" }
-
-
- { setmypt -- This isn't a timing function like the others; it's a replacement
- for the ROM's "setpt" routine, to see how fast we can do it ourselves. }
- procedure setmypt (VAR pt: point; x, y: integer);
- begin;
- pt.h := x; pt.v := y; { assign to the coordinates; easy! }
- end; { procedure "setmypt" }
-
- { myowntime -- Time the assignment using our own procedure. }
- function myowntime: longint;
- var
- count: longint; { loop counter }
- pt: point; { point to assign to }
- x, y: integer; { coordinates to assign to point }
- begin;
- start := tickcount; { snapshot starting time }
- for count := 1 to loops do { this time, inside the loop... }
- setmypt (pt, x, y); { ...we call our own routine }
- myowntime := tickcount-start; { calculate elapsed time }
- end; { function myowntime }
-
- { inlintime -- The most straightforward way: we do the assignment in the loop. }
- function inlintime: longint;
- var
- count: longint; { loop counter }
- pt: point; { point to assign to }
- x, y: integer; { coordinates to assign to point }
- begin;
- start := tickcount; { snapshot starting time }
- for count := 1 to loops do { this time, inside the loop... }
- begin; pt.h := x; pt.v := y; end; { ...we do the assignment right here }
- inlintime := tickcount-start; { calculate elapsed time }
- end; { function inlintime }
-
- { setptx -- This is another replacement for "setpt". It takes an extra
- parameter, the previously determined address of "setpt", and calls that
- address, leaving the other parameters for "setpt". Unfortunately, TML
- Pascal doesn't mimic Lisa Pascal closely enough to allow us to generate
- more than one word of code in a single declaration. So we have two
- procedures -- these MUST always be used together! TML says their 2.0
- release of the compiler will be Lisa-compatible on this score, so this
- unsightly workaround won't be needed any more. }
- procedure setptx1 (var pt: point; h, v: integer; addr: longint);
- INLINE $205F; { MOVE.L (A7)+,A0 ; pop routine's address into A0… }
- procedure setptx2;
- INLINE $4E90; { JSR (A0) ; …and call that address }
-
- { gettrtime -- The last and most complicated way of calling the routine. We
- use the trap address to call it directly. }
- function gettrtime: longint;
- var
- addr: longint; { actual address of "setpt" }
- count: longint; { loop counter }
- pt: point; { point to assign to }
- x, y: integer; { coordinates to assign to point }
- begin;
- addr := gettrapaddress ($a880); { find where the routine lives }
- start := tickcount; { snapshot starting time }
- for count := 1 to loops do begin { this time, inside the loop... }
- setptx1 (pt, x, y, addr); { ...we call on ROM, but differently }
- setptx2; { (kludge to sneak in 2nd instruction }
- end;
- gettrtime := tickcount-start; { calculate elapsed time }
- end; { function gettrtime }
-
- begin; { *** main program *** }
- writeln ('If launching from a floppy, wait for it to stop and click to begin...');
- while not button do; while button do; { cheap way to wait for a click }
-
- loops := 10000; { start with a small loop size... }
- while loops <= 100000 do { ...and go through several loop sizes }
- begin;
- basetime := getbasetime; { find constant overhead for the loop }
-
- writeln ('number of loops:', loops, '; base time is:', basetime);
- writeln ('time for usual method is..........: ', usualtime - basetime);
- writeln ('time for calling my own routine is: ', myowntime - basetime);
- writeln ('time for doing it in-line is......: ', inlintime - basetime);
- writeln ('time for doing it with gettrapaddr: ', gettrtime - basetime);
- writeln;
-
- loops := loops * 10; { loop sizes increase exponentially }
- end;
-
- flushevents(EveryEvent,0);
- writeln ('click to exit or take snapshot…'); { don't go away yet... }
- Repeat
- systemtask;
- DoIt:=GetNextEvent(EveryEvent,Event);
- if DoIt then
- Case Event.what of
- KeyDown: begin end;
- Mousedown: begin Finished:=true; end;
- End;
- Until Finished;
- end. { of main program "traptime" }
-